package com.qujia.common.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class LocalDateUtils {
    private static final ConcurrentMap<String, DateTimeFormatter> FORMATTER_CACHE = new ConcurrentHashMap();
    private static final int PATTERN_CACHE_SIZE = 100;
    public static final String DATETIME_FORMAT = "yyyyMMddHHmmss";
    public static final String DATETIME_12_FORMAT = "yyyy-MM-dd HH:mm";
    public static final String DATETIME_14_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String TIME_FORMAT = "HH:mm:ss";
    public static final String DATETIME_FORMAT_MS = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_8_FORMAT = "yyyyMMdd";
    public static final String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";

    public LocalDateUtils() {
    }

    private static DateTimeFormatter createCacheFormatter(String pattern) {
        if (pattern != null && pattern.length() != 0) {
            DateTimeFormatter formatter = (DateTimeFormatter)FORMATTER_CACHE.get(pattern);
            if (formatter == null && FORMATTER_CACHE.size() < 100) {
                formatter = DateTimeFormatter.ofPattern(pattern);
                DateTimeFormatter oldFormatter = (DateTimeFormatter)FORMATTER_CACHE.putIfAbsent(pattern, formatter);
                if (oldFormatter != null) {
                    formatter = oldFormatter;
                }
            }

            return formatter;
        } else {
            throw new IllegalArgumentException("Invalid pattern specification");
        }
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public static LocalDate dateToLocalDate(Date date) {
        return dateToLocalDateTime(date).toLocalDate();
    }

    public static LocalTime dateToLocalTime(Date date) {
        return dateToLocalDateTime(date).toLocalTime();
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static Date localDateToDate(LocalDate localDate) {
        Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    public static Date localTimeToDate(LocalTime localTime) {
        LocalDate localDate = LocalDate.now();
        Instant instant = LocalDateTime.of(localDate, localTime).atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    public static String format(LocalDateTime localDateTime, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return localDateTime.format(formatter);
    }

    public static String format(LocalDate localDate, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return localDate.format(formatter);
    }

    public static LocalDateTime parseLocalDateTime(String time, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return LocalDateTime.parse(time, formatter);
    }

    public static LocalDate parseLocalDate(String time, String pattern) {
        DateTimeFormatter formatter = createCacheFormatter(pattern);
        return LocalDate.parse(time, formatter);
    }

    public static LocalDateTime parseLocalDateTime(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
    }

    public static LocalDate parseLocalDate(long timestamp) {
        return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime parseLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    public static LocalDate parseLocalDate(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault()).toLocalDate();
    }

    public static boolean isDateStr8(String txnDate) {
        boolean result = true;
        if (txnDate.length() == 8) {
            SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");

            try {
                format.setLenient(false);
                format.parse(txnDate);
            } catch (ParseException var4) {
                result = false;
            }
        } else {
            result = false;
        }

        return result;
    }

    public static String getDateStrBySteps(String baseDate, int offset, String pattern) {
        return format(parseLocalDate(baseDate, pattern).plusDays((long)offset), pattern);
    }

    public static long periodDays(String startDate, String endDate, String pattern) {
        return parseLocalDate(startDate, pattern).until(parseLocalDate(endDate, pattern), ChronoUnit.DAYS);
    }

    public static LocalDateTime getFirstDayOfMonth(String yearMonthDateStr, int monthNum) {
        YearMonth yearMonth = YearMonth.parse(yearMonthDateStr);
        LocalDate localDate = LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1).plusMonths((long)monthNum);
        return localDate.atStartOfDay(ZoneId.systemDefault()).toLocalDateTime();
    }

    public static String getDayNameOfWeek(LocalDateTime localDateTime) {
        String[] daysOfWeek = new String[]{"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};
        return daysOfWeek[localDateTime.getDayOfWeek().getValue() - 1];
    }
}
